<template>
	<view class="colorPicker">
		<u-popup v-model="isShow" length="72%" mode="center" :closeable="false" border-radius="20" :mask-close-able="false">
			<view class="picker_main">
				<view class="t-color__box" :style="{ background: 'rgb(' + bgcolor.r + ',' + bgcolor.g + ',' + bgcolor.b + ')' }">
					<view class="t-background boxs_picker" @touchstart="touchstart($event, 0)" @touchmove="touchmove($event, 0)" @touchend="touchend($event, 0)">
						<view class="t-color-mask"></view>
						<view class="t-pointer" :style="{ top: site[0].top - 8 + 'px', left: site[0].left - 8 + 'px' }"></view>
					</view>
				</view>
				<view class="choice-info">
					<view class="left-info"><view :style="{ background: 'rgba(' + rgba.r + ',' + rgba.g + ',' + rgba.b + ',' + rgba.a + ')' }" class="info"></view></view>
					<view class="right-info">
						<view class="t-control__box">
							<view class="t-controller boxs_picker" @touchstart="touchstart($event, 1)" @touchmove="touchmove($event, 1)" @touchend="touchend($event, 1)">
								<view class="t-hue"><view class="t-circle" :style="{ left: site[1].left - 12 + 'px' }"></view></view>
							</view>
							<view class="t-controller boxs_picker" @touchstart="touchstart($event, 2)" @touchmove="touchmove($event, 2)" @touchend="touchend($event, 2)">
								<view class="t-transparency"><view class="t-circle" :style="{ left: site[2].left - 12 + 'px' }"></view></view>
							</view>
						</view>
					</view>
				</view>
				<view class="bottom-info">
					<view class="left" @click="confirm(0)">取消</view>
					<view class="right" @click="confirm(1)">确认</view>
				</view>
			</view>
		</u-popup>
	</view>
</template>

<script> 
export default {
	props: {
		color: {
			type: Object,
			default() {
				return { r: 0, g: 0, b: 0, a: 0 };
			}
		}
	},
	data() {
		return {
			isShow: false, //是否显示
			rgba: { r: 0, g: 0, b: 0, a: 1 },
			bgcolor: { r: 255, g: 0, b: 0, a: 1 },
			// hsb 颜色
			hsb: { h: 0, s: 0, b: 0 },
			site: [{ top: 0, left: 0 }, { left: 0 }, { left: 0 }],
			index: 0
		};
	},
	created() {
		this.rgba = this.color;
		this.hsb = this.rgbToHex(this.rgba);
	},
	methods: {
		open(color) {
			let that=this;
			that.isShow = true;
			that.rgba = color;
			that.hsb = that.rgbToHex(that.rgba);
			that.$nextTick(function(){
				that.getSelectorQuery();
			})
		},

		touchstart(e, index) {
			const { pageX, pageY } = e.touches[0];
			this.pageX = pageX;
			this.pageY = pageY;
			this.setPosition(pageX, pageY, index);
		},
		touchmove(e, index) {
			const { pageX, pageY } = e.touches[0];
			this.moveX = pageX;
			this.moveY = pageY;
			this.setPosition(pageX, pageY, index);
		},
		touchend(e, index) {},

		setPosition(x, y, index) {
			this.index = index;
			if (this.position == undefined) return;
			if (this.position.length <= index) return;
			const { top, left, width, height } = this.position[index];
			// 设置最大最小值
			this.site[index].left = Math.max(0, Math.min(parseInt(x - left), width));
			if (index === 0) {
				this.site[index].top = Math.max(0, Math.min(parseInt(y - top), height));
				// 设置颜色
				this.hsb.s = parseInt((100 * this.site[index].left) / width);
				this.hsb.b = parseInt(100 - (100 * this.site[index].top) / height);
				this.setColor();
			} else {
				this.setControl(index, this.site[index].left);
			}
		},
		setControl(index, x) {
			const { top, left, width, height } = this.position[index];
			if (index === 1) {
				this.hsb.h = parseInt((360 * x) / width);
				this.bgcolor = this.HSBToRGB({
					h: this.hsb.h,
					s: 100,
					b: 100
				});
				this.setColor();
			} else {
				this.rgba.a = (x / width).toFixed(1);				
			}
		},

		/**
		 * 设置 rgb 颜色
		 */
		setColor() {
			const rgb = this.HSBToRGB(this.hsb);
			this.rgba.r = rgb.r;
			this.rgba.g = rgb.g;
			this.rgba.b = rgb.b;			
		},

		confirm(type) {
			this.isShow=false;
			this.$emit('confirm', {
				rgba: this.rgba,
				type
			});
		},

		/**
		 * hsb 转 rgb
		 * @param {Object} 颜色模式  H(hues)表示色相，S(saturation)表示饱和度，B（brightness）表示亮度
		 */
		HSBToRGB(hsb) {
			let rgb = {};
			let h = Math.round(hsb.h);
			let s = Math.round((hsb.s * 255) / 100);
			let v = Math.round((hsb.b * 255) / 100);
			if (s == 0) {
				rgb.r = rgb.g = rgb.b = v;
			} else {
				let t1 = v;
				let t2 = ((255 - s) * v) / 255;
				let t3 = ((t1 - t2) * (h % 60)) / 60;
				if (h == 360) h = 0;
				if (h < 60) {
					rgb.r = t1;
					rgb.b = t2;
					rgb.g = t2 + t3;
				} else if (h < 120) {
					rgb.g = t1;
					rgb.b = t2;
					rgb.r = t1 - t3;
				} else if (h < 180) {
					rgb.g = t1;
					rgb.r = t2;
					rgb.b = t2 + t3;
				} else if (h < 240) {
					rgb.b = t1;
					rgb.r = t2;
					rgb.g = t1 - t3;
				} else if (h < 300) {
					rgb.b = t1;
					rgb.g = t2;
					rgb.r = t2 + t3;
				} else if (h < 360) {
					rgb.r = t1;
					rgb.g = t2;
					rgb.b = t1 - t3;
				} else {
					rgb.r = 0;
					rgb.g = 0;
					rgb.b = 0;
				}
			}
			return {
				r: Math.round(rgb.r),
				g: Math.round(rgb.g),
				b: Math.round(rgb.b)
			};
		},
		rgbToHsb(rgb) {
			let hsb = {
				h: 0,
				s: 0,
				b: 0
			};
			let min = Math.min(rgb.r, rgb.g, rgb.b);
			let max = Math.max(rgb.r, rgb.g, rgb.b);
			let delta = max - min;
			hsb.b = max;
			hsb.s = max != 0 ? (255 * delta) / max : 0;
			if (hsb.s != 0) {
				if (rgb.r == max) hsb.h = (rgb.g - rgb.b) / delta;
				else if (rgb.g == max) hsb.h = 2 + (rgb.b - rgb.r) / delta;
				else hsb.h = 4 + (rgb.r - rgb.g) / delta;
			} else hsb.h = -1;
			hsb.h *= 60;
			if (hsb.h < 0) hsb.h = 0;
			hsb.s *= 100 / 255;
			hsb.b *= 100 / 255;
			return hsb;
		},
		/**
		 * rgb 转 二进制 hex
		 * @param {Object} rgb
		 */
		rgbToHex(rgb) {
			let hex = [rgb.r.toString(16), rgb.g.toString(16), rgb.b.toString(16)];
			hex.map(function(str, i) {
				if (str.length == 1) {
					hex[i] = '0' + str;
				}
			});
			return hex.join('');
		},

		getSelectorQuery() {
			const views = uni.createSelectorQuery().in(this);
			views
				.selectAll('.boxs_picker')
				.boundingClientRect(data => {
					if (!data || data.length === 0) {
						setTimeout(() => this.getSelectorQuery(), 20);
						return;
					}
					data.forEach((item, index) => {
						if (index == 0) {
							item.width -= 40;
							item.height -= 42;
						} else {
							item.width -= 24;
							item.height -= 38;
						}
					});
					this.position = data;
					// this.site[0].top = data[0].height;
					// this.site[0].left = 0;
					// this.site[1].left = data[1].width;
					// this.site[2].left = data[2].width;
					this.setColorBySelect(this.rgba);
				})
				.exec();
		},
		setColorBySelect(getrgb) {
			const { r, g, b, a } = getrgb;
			let rgb = {};
			rgb = {
				r: r ? parseInt(r) : 0,
				g: g ? parseInt(g) : 0,
				b: b ? parseInt(b) : 0,
				a: a ? a : 0
			};
			this.rgba = rgb;
			this.hsb = this.rgbToHsb(rgb);
			this.changeViewByHsb();
		},
		changeViewByHsb() {
			const [a, b, c] = this.position;
			this.site[0].left = parseInt((this.hsb.s * a.width) / 100);
			this.site[0].top = parseInt(((100 - this.hsb.b) * a.height) / 100);
			this.bgcolor = this.HSBToRGB({
				h: this.hsb.h,
				s: 100,
				b: 100
			});
			let rgb = this.HSBToRGB(this.hsb);
			this.rgba.r = rgb.r;
			this.rgba.g = rgb.g;
			this.rgba.b = rgb.b;
			// console.log(JSON.stringify(this.rgba))
			this.site[1].left = (this.hsb.h / 360) * b.width;
			this.site[2].left = this.rgba.a * c.width;
		}
	}
};
</script>

<style lang="scss">
.colorPicker {
	.picker_main {
		display: flex;
		flex-direction: column;
		.t-color__box {
			position: relative;
			height: 540upx;
			background: rgb(255, 0, 0);
			overflow: hidden;
			box-sizing: border-box;
			margin: 0 20upx;
			margin-top: 20upx;
			box-sizing: border-box;
			border: 1upx solid #f7f7f7;
		}

		.t-background {
			position: absolute;
			top: 0;
			left: 0;
			right: 0;
			bottom: 0;
			background: linear-gradient(to right, #fff, rgba(255, 255, 255, 0));
		}

		.t-color-mask {
			position: absolute;
			top: 0;
			left: 0;
			right: 0;
			bottom: 0;
			width: 100%;
			height: 540upx;
			background: linear-gradient(to top, #000, rgba(0, 0, 0, 0));
		}

		.t-pointer {
			position: absolute;
			bottom: -8px;
			left: -8px;
			z-index: 2;
			width: 15px;
			height: 15px;
			border: 1px #fff solid;
			border-radius: 50%;
		}

		.t-show-color {
			width: 100upx;
			height: 50upx;
		}

		.choice-info {
			display: flex;
			flex-direction: row;
			justify-content: space-around;
			margin-top: 40upx;
			padding: 0 30upx;
			.left-info {
				display: flex;
				flex-direction: row;
				align-items: center;
				justify-content: center;
				width: 84upx;
				height: 84upx;
				margin-right: 36upx;
				border: 1upx solid #dcdfe6;
				border-radius: 50%;
				padding: 2upx;
				margin-top: -12upx;
				.info {
					width: 100%;
					height: 100%;
					border-radius: 50%;
					background-color: #f0ad4e;
				}
			}
			.right-info {
				position: relative;
				width: calc(100% - 120upx);
			}
		}

		.t-control__box {
			width: 100%;
			display: flex;
			flex-direction: column;
			justify-content: space-between;
			box-sizing: border-box;
		}

		.t-controller {
			position: relative;
			width: 100%;
			height: 16upx;
			margin-bottom: 30upx;
			background-color: #fff;
			background-image: linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee),
				linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee);
			background-size: 32upx 32upx;
			background-position: 0 0, 16upx 16upx;
		}

		.t-hue {
			width: 100%;
			height: 100%;
			background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
		}

		.t-transparency {
			width: 100%;
			height: 100%;
			background: linear-gradient(to right, rgba(0, 0, 0, 0) 0%, rgb(0, 0, 0));
		}

		.t-circle {
			position: absolute;
			/* right: -10px; */
			top: -6px;
			width: 20px;
			height: 20px;
			box-sizing: border-box;
			border-radius: 50%;
			background: #fff;
			box-shadow: 0 0 2px 1px rgba(0, 0, 0, 0.1);
		}
		.bottom-info {
			margin-top: 20upx;
			margin-bottom: 8upx;
			border-top: 2upx solid rgba($color:  #9e9e9e, $alpha: 0.6);
			padding: 24upx 0;
			display: flex;
			flex-direction: row;
			align-items: center;
			justify-content: space-between;
			.left,
			.right {
				width: 50%;
				text-align: center;
			}
			.left {
				border-right: 2upx solid rgba($color:  #9e9e9e, $alpha: 0.6);
			}
			.right {
				border-left: 2upx solid rgba($color:  #9e9e9e, $alpha: 0.6);
				color: #007AFF;
			}
		}
	}
}
</style>
